<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>ObserverNav</title>
</head>
<style>
    .zxx_main_con article,
    .zhxx_main_con article {
        font-size: medium;
    }
    .zxx_main_con p,
    .zhxx_main_con p {
        margin: 1em 0;
    }
    .zxx_main_con h3,
    .zhxx_main_con h3 {
        margin: 1.2em 0;
        background-color: #333;
        color: #fff;
        padding: 10px;
    }
    .zxx_main_con h4,
    .zhxx_main_con h4,
    .zxx_main_con h5,
    .zhxx_main_con h5 {
        font-size: 100%;
    }
    .zxx_main_con pre,
    .zhxx_main_con pre {
        padding: .5em 1em;
        background-color: #f3f5f9;
        font-family: Consolas, Monaco, monospace;
    }
</style>
<style>
    .title-fixed {
        min-width: 220px;
        background-color: #fff;
        position: fixed;
        top: 20px; right: 10px;
        padding: 0 0 0 15px;
    }
    .title-nav-ul {
        /*width: 100%;*/
    }
    .title-nav-li {
        display: block;
        text-decoration: none;
        color: inherit;
        height: 40px;
        line-height: 40px;
        box-sizing: border-box;
    }
    .title-nav-li.active {
        font-weight: bold;
    }
    .title-nav-li:hover {
        color: inherit;
        background-color: #f0f0f0;
        text-decoration: none;
    }
    .title-fixed:before {
        content: '';
        position: absolute;
        height: 100%;
        width: 2px;
        left: 5px;
        background-color: #e4e7ed;
    }
    .title-bar {
        position: absolute;
        content: '';
        width: 2px;
        height: 40px;
        background-color: green;
        left: 5px;
        top: 0;
        transition: transform .1s cubic-bezier(.645,.045,.355,1);
    }
</style>
<body>
<div class="zhxx_main_con">
    <article>
        <h3>一、为何叫LuLu？</h3>
        <p>气质相符。</p>
        <p><img src="//qidian.gtimg.com/lulu/theme/modern/css/common/images/temp/figure.png" width="122" height="137"></p>
        <h3>二、为什么使用LuLu？</h3>
        <ol>
            <li>
                <h4>已迭代多年</h4>
                <p>始于2015年，已成功支持多个千万PV大型项目，迭代优化多年，较成熟。</p>
            </li>
            <li>
                <h4>上手简单</h4>
                <p>会简单HTML和jQuery就可以上手了，不像一些流行框架，需要较多的学习成本。</p>
            </li>
            <li>
                <h4>使用方式灵活</h4>
                <p>支持类似seajs这种模块化加载，同时也支持一个一个<code>&lt;script&gt;</code>直接加载调用。</p>
            </li>
            <li>
                <h4>体验和细节很棒</h4>
                <p>体验和细节很棒，包括：</p>
                <h5>①. 代码质量高</h5>
                <p>eslint对格式进行严格控制，同时有比较详细的注释，API命名和变量命名等至始至终风格一致，方便理解、修改与学习。</p>
                <h5>②. retina支持</h5>
                <p>所有UI组件都是支持retina显示的。主要应用了CSS生成技术，以及SVG的处理。</p>
                <p>且每个组件的小图标独立使用，不耦合，使用base64技术，减少无谓的额外http请求，IE7/IE8使用图片向下兼容。</p>
                <pre>.icon {
background: url(test.png);
background: url(data:image/svg+xml;base64,…), none;
}</pre>
                <h5>③. 交互细腻</h5>
                <p>渐进增强使用CSS3 <code>animation</code>和<code>transition</code>，以较低成本增强组件交互体验。同时，兼顾<code>hover</code>延迟，弹框背景锁定，组件可视区域控制等很多细节处理。</p>
            </li>
            <li>
                <h4>无障碍访问支持</h4>
                <p>peak主题下，增加了Aria屏幕阅读设备无障碍访问以及键盘无障碍访问支持。</p>
            </li>
        </ol>

        <h3 >三、设计理念</h3>
        <ol>
            <li>
                <h4>面向设计开发</h4>
                <p>关于面向设计开发可参见这里：“<a target="_blank" href="//www.zhangxinxu.com/wordpress/?p=4892">面向设计的半封装web组件开发</a>”。</p>

                <p>面向设计最大的特点在于能够对设计进行最完美的还原，可以很好地展现设计品质。有别于先有组件，然后再制约设计的设计策略。</p>
                <p>所以，LuLu UI是没有版本的概念的，只有一条核心线自己往前走。当新项目过来需要使用的时候，完全拷贝LuLu UI到项目开发目录中，然后根据当前项目的设计风格，对HTML和JS进行结构上的调整，是放心大胆的调整。</p>
                <p>因此，LuLu UI组件不是传统的大而全，而是走极简轻便灵活方向，表现为模块低耦合，层级扁平；API非常少，尤其一些基本组件，直接就没有API。</p>
                <p>LuLu UI没有版本概念，只有主题。目前有morden和peak两个主题。寓意为“现代”和“巅峰”。morden主题兼容IE7+，目前已停止维护，因为项目已经放弃对IE7的兼容；peak主题兼容IE8+，是目前持续维护和迭代的版本。</p>
            </li>
            <li>
                <h4>基于HTML开发</h4>
                <p>相对于其他UI框架，LuLu UI技术栈更偏向HTML和CSS，以便更友好地还原设计和增强体验。</p>
                <p>具体而言，LuLu UI基于HTML开发，实现前端开发分离，具体可参考“<a href="//www.zhangxinxu.com/wordpress/?p=5180">顺势而为，HTML发展与UI组件设计进化</a>”。</p>
                <p>换句话说，开发的时候，只需要关心原生的HTML控件就可以，组件什么的不用在意。例如，时间选择，当我们选择或修改日期，就直接当组件不存在，处理原生input就好了：</p>
                <pre>$("input").change(function() {});</pre>
                <p>想要修改日期范围，很简单，直接改变原生的属性值就好了：</p>
                <pre>$("input").attr({
"min": "2015-07-01",
"max": "2015-09-01"
});</pre>
                <p>组件自动就会同步，就跟原生的时间选择组件感觉一样！</p>
                <p>所谓UI组件，本来就应该只负责UI，跟业务没有瓜葛才对。</p>
                <p>LuLu中的很多UI组件都是采用这样的设计思想。</p>
            </li>
        </ol>
        <h3 >四、滚动到底部我高亮</h3>
        <p>试试看</p>
    </article>
</div>

<div class="title-fixed">
    <div class="title-bar"></div>
</div>
<h2>test</h2>
<script>
    let smartNav = function (elements, options) {
        let defaults = {
            nav: null
        }

        let params = Object.assign({}, defaults, options || {})

        if (typeof elements == 'string') {
            elements = document.querySelectorAll(elements)
        }

        if (!elements.forEach) {
            return
        }

        // 导航元素创建，如果没有
        if (!params.nav) {
            params.nav = document.createElement('div')
            params.nav.className = 'title-nav-ul'
            // document.body.appendChild(params.nav)
            document.querySelector('.title-fixed').appendChild(params.nav)
        }

        let lastScrollTop = document.scrollingElement.scrollTop

        let zxxObserver = new IntersectionObserver(function (entries) {
            if (params.isAvoid) {
                return
            }
            entries.reverse().forEach(function (entry) {
                if (entry.isIntersecting) {
                    entry.target.active()
                } else if (entry.target.isActived) {
                    entry.target.unactive()
                }
            })

            lastScrollTop = document.scrollingElement.scrollTop
        })

        elements.forEach(function (ele, index) {
            let id = ele.id || ('smartNav' + Math.random()).replace('0.', '')
            ele.id = id
            // 导航元素创建
            let eleNav = document.createElement('a')
            eleNav.href = '#' + id
            eleNav.className = 'title-nav-li'
            eleNav.innerHTML = ele.textContent
            eleNav.setAttribute('data-index', index+1)
            params.nav.appendChild(eleNav)
            ele.active = function () {
                // 对应的导航元素高亮
                eleNav.parentElement.querySelectorAll('.active').forEach(function (eleActive) {
                    ele.isActived = false
                    eleActive.classList.remove('active')
                })
                eleNav.classList.add('active')
                ele.isActived = true;
                dealTransformHeight(eleNav.getAttribute('data-index'))
            }
            ele.unactive = function () {
                // 对应的导航元素高亮
                if (document.scrollingElement.scrollTop > lastScrollTop) {
                    elements[index + 1] && elements[index + 1].active()
                } else {
                    elements[index - 1] && elements[index - 1].active()
                }
                eleNav.classList.remove('active')
                ele.isActived = false
            }

            // 观察元素
            zxxObserver.observe(ele)
        });

        params.nav.addEventListener('click', function (event) {
            let eleLink = event.target.closest('a')
            // 导航对应的标题元素
            let eleTarget = eleLink && document.querySelector(eleLink.getAttribute('href'))
            if (eleTarget) {
                event.preventDefault()
                // Safari不支持平滑滚动
                eleTarget.scrollIntoView({
                    behavior: "smooth",
                    block: 'center'
                })

                if (CSS.supports('scroll-behavior: smooth')) {
                    params.isAvoid = true
                    setTimeout(function () {
                        eleTarget.active()
                        params.isAvoid = false
                    }, Math.abs(eleTarget.getBoundingClientRect().top  - window.innerHeight / 2) / 2)
                } else {
                    eleTarget.active()
                }
            }
        });
    }
    function dealTransformHeight (activeIndex) {
        document.querySelectorAll('.title-nav-li').forEach((item, index)=>{
            if(Array.from(item.classList).length == 2) {
                let barIsTop = document.querySelector('.title-bar').offsetHeight
                let num = barIsTop % 40
                document.querySelector('.title-bar').style.transform = `translateY(${(index - num)*40 + 'px'})`
            }
        })
        return
        let barIsTop = document.querySelector('.title-bar').offsetHeight
        let num = barIsTop % 40
        console.log(`translateY(${(activeIndex - num)*40 + 'px'})`)
        document.querySelector('.title-bar').style.transform = `translateY(${(activeIndex +1 - num)*40 + 'px'})`
    }

    smartNav('article h3')

    // test
    const intersectionObserver = new IntersectionObserver((entries) => {
        // If intersectionRatio is 0, the target is out of view
        // we do not need to do anything.
        // if (entries[0].intersectionRatio <= 0) return

        console.log(entries)
    })
    // start observing
    intersectionObserver.observe(document.querySelector('h2'))
</script>
</body>
</html>